// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.

package freechips.rocketchip.rocket

import Chisel._
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.tile.CoreModule

/** 基本的ALU单元
  */

// ALU指令常数和简单函数定义
object ALU
{
  val SZ_ALU_FN = 4   // TBD: 为啥使用4bit？如何来的？
  def FN_X    = BitPat("b????")   // 默认匹配项
  def FN_ADD  = UInt(0)   // 加
  def FN_SL   = UInt(1)   // 左移
  def FN_SEQ  = UInt(2)   // 相等
  def FN_SNE  = UInt(3)   // 不等
  def FN_XOR  = UInt(4)   // 异或
  def FN_SR   = UInt(5)   // Shift Right
  def FN_OR   = UInt(6)   // 或
  def FN_AND  = UInt(7)   // 与
  def FN_SUB  = UInt(10)  // 减
  def FN_SRA  = UInt(11)  // Shift Right Arithmetic
  def FN_SLT  = UInt(12)  // 小于
  def FN_SGE  = UInt(13)  // 大于
  def FN_SLTU = UInt(14)  // 无符号小于
  def FN_SGEU = UInt(15)  // 无符号大于

  def FN_DIV  = FN_XOR      // 除法
  def FN_DIVU = FN_SR     // 无符号除
  def FN_REM  = FN_OR  // 余数
  def FN_REMU = FN_AND

  def FN_MUL    = FN_ADD    //乘法
  def FN_MULH   = FN_SL
  def FN_MULHSU = FN_SEQ
  def FN_MULHU  = FN_SNE

  def isMulFN(fn: UInt, cmp: UInt) = fn(1,0) === cmp(1,0)
  def isSub(cmd: UInt) = cmd(3)   // 是否相减操作：1010 VS 0000
  def isCmp(cmd: UInt) = cmd >= FN_SLT  // 是否比较：12,13,14,15
  def cmpUnsigned(cmd: UInt) = cmd(1)  // 无符号比较: 12,14 VS 13,15
  def cmpInverted(cmd: UInt) = cmd(0) // 
  def cmpEq(cmd: UInt) = !cmd(3) // 
}

// 导入常数
import ALU._

class ALU(implicit p: Parameters) extends CoreModule()(p) {
  val io = new Bundle {
    val dw = Bits(INPUT, SZ_DW)         // 是否支持64bit定义. 看起来是32bit/64bit兼容设计
    val fn = Bits(INPUT, SZ_ALU_FN)     // 4bit fn
    val in2 = UInt(INPUT, xLen)         // rs2：xLen为ALU计算数据宽度
    val in1 = UInt(INPUT, xLen)         // rs1
    val out = UInt(OUTPUT, xLen)        // rd
    val adder_out = UInt(OUTPUT, xLen)  // TBD: 额外的加法结果
    val cmp_out = Bool(OUTPUT)          // TBD: 额外的比较结果
  }

  // ADD, SUB
  val in2_inv = Mux(isSub(io.fn), ~io.in2, io.in2)  // 相减则取反
  val in1_xor_in2 = io.in1 ^ in2_inv  // 异或
  io.adder_out := io.in1 + in2_inv + isSub(io.fn)  // 相加，或者取反加1

  // SLT, SLTU
  val slt =
    Mux(io.in1(xLen-1) === io.in2(xLen-1), io.adder_out(xLen-1),   // 符号为相同，返回相减结果的高位（正负位）
    Mux(cmpUnsigned(io.fn), io.in2(xLen-1), io.in1(xLen-1)))  // 否则（一个正，一个负），若无符号比较，返回in2高位
  io.cmp_out := cmpInverted(io.fn) ^ Mux(cmpEq(io.fn), in1_xor_in2 === UInt(0), slt)

  // SLL, SRL, SRA
  val (shamt, shin_r) =  // 计算移位量和移位数
    if (xLen == 32) (io.in2(4,0), io.in1)
    else {
      require(xLen == 64)
      val shin_hi_32 = Fill(32, isSub(io.fn) && io.in1(31))
      val shin_hi = Mux(io.dw === DW_64, io.in1(63,32), shin_hi_32)
      val shamt = Cat(io.in2(5) & (io.dw === DW_64), io.in2(4,0))
      (shamt, Cat(shin_hi, io.in1(31,0)))
    }
  val shin = Mux(io.fn === FN_SR  || io.fn === FN_SRA, shin_r, Reverse(shin_r))   // 右移为正，否则取反
  val shout_r = (Cat(isSub(io.fn) & shin(xLen-1), shin).asSInt >> shamt)(xLen-1,0)  // 右移
  val shout_l = Reverse(shout_r) // 左移
  val shout = Mux(io.fn === FN_SR || io.fn === FN_SRA, shout_r, UInt(0)) |
              Mux(io.fn === FN_SL,                     shout_l, UInt(0))

  // AND, OR, XOR
  val logic = Mux(io.fn === FN_XOR || io.fn === FN_OR, in1_xor_in2, UInt(0)) |   // 同时计算3个
              Mux(io.fn === FN_OR || io.fn === FN_AND, io.in1 & io.in2, UInt(0))
  val shift_logic = (isCmp(io.fn) && slt) | logic | shout
  val out = Mux(io.fn === FN_ADD || io.fn === FN_SUB, io.adder_out, shift_logic)

  io.out := out
  if (xLen > 32) {  // 专门针对64bit的电路：补充32bit的高位？
    require(xLen == 64)
    when (io.dw === DW_32) { io.out := Cat(Fill(32, out(31)), out(31,0)) }  // xlen=64，但当前操作是32bit时---- 后向兼容
  }
}
